#pragma once
#include "GameComponent.h"
#include "util/Shared_ptr.h"
#include "physics/IObserverPhysics.h"
#include "Bounds.h"
#include "physics/MaterialPhysics.h"
#include "physics/IObserverPhysics.h"




namespace Boon
{
	//fwds
	class Bounds;
	namespace Physics { class IPhysics; class SimulationCallback; }

	
	/*!
	* Collider representing an abstract collision-shape
	*/
	class BOON_API Collider : public GameComponent, public IObserverPhysics
	{
		enum ColliderFlags
		{
			CF_DIRTY = 1,
			CF_IS_TRIGGER = 2
		};

	protected:
		Collider( const char* compName, Boon::GameObject* g );

	public:
		

		inline void						SetTrigger( bool flag ) {/*clear bit*/m_Flags &= ~(CF_IS_TRIGGER);/*set bit*/ if( flag ) m_Flags |= CF_IS_TRIGGER; SetDirty(); }
		inline bool						IsTrigger() const{ return ( m_Flags & CF_IS_TRIGGER ) > 0; }
		inline MaterialPhysics&			GetMaterial() { return m_Material; }
		inline void						SetMaterial( const MaterialPhysics& mat ) { m_Material = mat; }
		virtual Bounds					GetBounds() const = 0;
		virtual ColliderType			GetType() const = 0;

		bool							Register( const ComponentID& id, const IObserverPhysicsStrong& );
		bool							Remove( const ComponentID& id );

	protected:
		virtual void					OnCreate();
		virtual void					OnEnable();
		virtual void					OnStart();
		virtual void					Update();
		virtual void					LateUpdate();
		virtual void					OnDisable();
		virtual void					OnDestroy();
		inline void						SetDirty(){  /*clear bit*/m_Flags &= ~(CF_DIRTY); /*set bit*/m_Flags |= CF_DIRTY; }

	private:

		virtual void					OnTriggerEnter( const Collider& collider );
		virtual void					OnTriggerExit( const Collider& collider );
		virtual void					OnTriggerStay( const Collider& collider );

		virtual void					OnCollisionEnter( const Collider& collider );
		virtual void					OnCollisionExit( const Collider& collider );
		virtual void					OnCollisionStay( const Collider& collider );

		inline void						NotifyObserver( void (IObserverPhysics::*observerCallback)( const Collider& c ), const Collider& c );

		std::map<ComponentID, IObserverPhysicsStrong>		m_Observer;
		unsigned char										m_Flags;
		MaterialPhysics										m_Material;

		friend class Physics::NvidiaPhysX;
		friend class Boon::Physics::SimulationCallback;
	};


}
